<script lang="tsx" setup>
import { onMounted, onUnmounted, ref, computed } from 'vue';
import VirtualLogViewer from '@/components/custom/virtual-log-viewer.vue';

defineOptions({ name: 'SystemLog' });

interface LogFile {
    name: string;
    path: string;
}

interface FileCache {
    lines: string[];
    totalSize: number;
    lastUpdate: number;
    offset: number;
}

const loading = ref(false);
const virtualLogRef = ref<InstanceType<typeof VirtualLogViewer>>();

// 文件相关状态
const selectedDirectory = ref<string>('');
const logFiles = ref<LogFile[]>([]);
const selectedFile = ref<string>('');
const searchKeyword = ref<string>('');

// 日志内容和缓存
const logLines = ref<string[]>([]);
const fileCache = ref<Map<string, FileCache>>(new Map());
const maxCacheSize = 10000; // 最大缓存行数
const maxCacheAge = 5 * 60 * 1000; // 5分钟缓存过期

// 定时器和状态
const timerRef = ref<number | null>(null);
const isReading = ref(false);
const currentSearchIndex = ref(0);
const searchResults = ref<number[]>([]);

// 计算属性
const fileInfo = computed(() => {
    const cache = fileCache.value.get(selectedFile.value);
    if (!cache) return null;

    return {
        totalLines: cache.lines.length,
        fileSize: formatFileSize(cache.totalSize),
        lastUpdate: new Date(cache.lastUpdate).toLocaleTimeString()
    };
});

// 格式化文件大小
function formatFileSize(bytes: number): string {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

// 选择目录
async function selectDirectory() {
    try {
        const dirPath = await window?.electronAPI?.selectDirectory();
        if (dirPath) {
            selectedDirectory.value = dirPath;
            await loadLogFiles();
        }
    } catch (error) {
        console.error('选择目录失败:', error);
        window.$message?.error($t('log.systemLog.selectDirectoryFailed'));
    }
}

// 加载日志文件列表
async function loadLogFiles() {
    if (!selectedDirectory.value) return;

    try {
        loading.value = true;
        const files = await window?.electronAPI?.getLogFiles(selectedDirectory.value);
        logFiles.value = files.map((filePath: string) => ({
            name: filePath.split('\\').pop() || filePath.split('/').pop() || '',
            path: filePath
        }));
    } catch (error) {
        console.error('加载文件列表失败:', error);
        window.$message?.error($t('log.systemLog.loadFileListFailed'));
    } finally {
        loading.value = false;
    }
}

// 选择文件
async function selectFile(filePath: string) {
    if (selectedFile.value === filePath) return;

    // 停止当前文件的读取
    stopReading();
    selectedFile.value = filePath;

    // 从缓存加载或重新读取文件
    await loadFileContent(filePath);

    // 开始定时读取
    startReading();
}

// 加载文件内容（使用尾部读取策略）
async function loadFileContent(filePath: string, incremental = false) {
    try {
        loading.value = true;
        const cache = fileCache.value.get(filePath);
        const now = Date.now();

        // 检查缓存是否有效
        if (cache && !incremental && now - cache.lastUpdate < maxCacheAge) {
            logLines.value = [...cache.lines];
            return;
        }

        if (incremental && cache) {
            // 增量读取
            const result = await window?.electronAPI?.readFileIncremental({
                path: filePath,
                lastSize: cache.totalSize
            });

            if (result && result.content && result.isIncremental) {
                const newLines = result.content
                    .split('\n')
                    .filter((line) => line.trim().length > 0);
                if (newLines.length > 0) {
                    const updatedLines = [...cache.lines, ...newLines];

                    // 限制总行数以避免内存问题
                    const finalLines =
                        updatedLines.length > maxCacheSize
                            ? updatedLines.slice(-maxCacheSize)
                            : updatedLines;

                    logLines.value = finalLines;
                    updateCache(filePath, finalLines, result.actualSize || result.size);
                }
            }
        } else {
            // 初始加载：读取文件头部（从第一行开始）
            const result = await window?.electronAPI?.readFileHead({
                path: filePath,
                lines: 5000 // 增加初始加载行数到5000行
            });

            if (result && result.lines) {
                logLines.value = result.lines;
                updateCache(filePath, result.lines, result.totalSize);

                // 如果文件还有更多内容，继续加载
                if (result.lines.length >= 5000 && result.hasMore) {
                    await loadMoreContent(filePath, result.lines.length);
                }
            }
        }
    } catch (error) {
        console.error('读取文件失败:', error);
        window.$message?.error($t('log.systemLog.readFileFailed'));
    } finally {
        loading.value = false;
    }
}

// 加载更多内容的函数
async function loadMoreContent(filePath: string, currentLines: number) {
    try {
        const result = await window?.electronAPI?.readFileHead({
            path: filePath,
            lines: -1 // -1 表示读取整个文件
        });

        if (result && result.lines && result.lines.length > currentLines) {
            logLines.value = result.lines;
            updateCache(filePath, result.lines, result.totalSize);
        }
    } catch (error) {
        console.error('加载更多内容失败:', error);
        window.$message?.error($t('log.systemLog.loadMoreContentFailed'));
    }
}

// 更新缓存
function updateCache(filePath: string, lines: string[], totalSize: number) {
    // 清理过期缓存
    cleanCache();

    fileCache.value.set(filePath, {
        lines: lines, // 保留完整的行数据
        totalSize,
        lastUpdate: Date.now(),
        offset: 0
    });
}

// 清理缓存
function cleanCache() {
    const now = Date.now();

    for (const [key, cache] of fileCache.value.entries()) {
        if (now - cache.lastUpdate > maxCacheAge) {
            fileCache.value.delete(key);
        }
    }
}

// 开始定时读取
function startReading() {
    if (!selectedFile.value || isReading.value) return;

    isReading.value = true;
    timerRef.value = window.setInterval(async () => {
        if (selectedFile.value) {
            await loadFileContent(selectedFile.value, true);
        }
    }, 1000);
}

// 停止读取
function stopReading() {
    isReading.value = false;
    if (timerRef.value) {
        clearInterval(timerRef.value);
        timerRef.value = null;
    }
}

// 搜索功能
function searchInLog() {
    if (!searchKeyword.value || !virtualLogRef.value) return;

    searchResults.value = virtualLogRef.value.findMatchingLines(searchKeyword.value);
    currentSearchIndex.value = 0;

    if (searchResults.value.length > 0) {
        virtualLogRef.value.scrollToLine(searchResults.value[0]);
        window.$message?.success($t('log.systemLog.foundMatches', { count: searchResults.value.length }));
    } else {
        window.$message?.warning($t('log.systemLog.noMatchFound'));
    }
}

// 下一个搜索结果
function nextSearchResult() {
    if (searchResults.value.length === 0 || !virtualLogRef.value) return;

    currentSearchIndex.value = (currentSearchIndex.value + 1) % searchResults.value.length;
    virtualLogRef.value.scrollToLine(searchResults.value[currentSearchIndex.value]);
}

// 上一个搜索结果
function prevSearchResult() {
    if (searchResults.value.length === 0 || !virtualLogRef.value) return;

    currentSearchIndex.value =
        currentSearchIndex.value === 0
            ? searchResults.value.length - 1
            : currentSearchIndex.value - 1;
    virtualLogRef.value.scrollToLine(searchResults.value[currentSearchIndex.value]);
}

// 清空日志
function clearLog() {
    logLines.value = [];
    if (selectedFile.value) {
        fileCache.value.delete(selectedFile.value);
    }
    searchResults.value = [];
    currentSearchIndex.value = 0;
}

// 滚动到底部
function scrollToBottom() {
    virtualLogRef.value?.scrollToBottom();
}

// 滚动到顶部
function scrollToTop() {
    virtualLogRef.value?.scrollTo({ top: 0 });
}

// 添加高度相关的响应式变量
const containerHeight = ref(800); // 默认高度
const sidebarHeight = computed(() => containerHeight.value - 32); // 减去padding
const logViewerHeight = computed(() => containerHeight.value - 120); // 减去header高度

onMounted(() => {
    // 组件挂载时的初始化逻辑
});

onUnmounted(() => {
    stopReading();
});
</script>

<template>
    <div class="system-log-container" :style="{ height: containerHeight + 'px' }">
        <div class="log-sidebar" :style="{ height: sidebarHeight + 'px' }">
            <div class="sidebar-header">
                <NButton type="primary" @click="selectDirectory" :loading="loading">
                    {{ $t('common.config') }}{{ $t('log.systemLog.title') }}
                </NButton>
                <div v-if="selectedDirectory" class="selected-dir">
                    <NText depth="3" class="color-white" style="font-size: 12px">{{
                        selectedDirectory
                    }}</NText>
                </div>
            </div>

            <div class="file-list" :style="{ height: 'calc(100% - 200px)' }">
                <NList v-if="logFiles.length > 0" hoverable clickable>
                    <NListItem
                        v-for="file in logFiles"
                        :key="file.path"
                        @click="selectFile(file.path)"
                        :class="{ active: selectedFile === file.path }"
                    >
                        <NText>{{ file.name }}</NText>
                    </NListItem>
                </NList>
                <NEmpty v-else :description="$t('log.systemLog.noLogFiles')" />
            </div>

            <!-- 文件信息 -->
            <div v-if="fileInfo" class="file-info">
                <NDivider style="margin: 12px 0">{{ $t('log.systemLog.fileInfo') }}</NDivider>
                <div class="info-item">
                    <NText class="color-white" depth="3">{{ $t('log.systemLog.totalLines') }}:</NText>
                    <NText class="color-white">{{ fileInfo.totalLines }}</NText>
                </div>
                <div class="info-item">
                    <NText class="color-white" depth="3">{{ $t('log.systemLog.fileSize') }}:</NText>
                    <NText class="color-white">{{ fileInfo.fileSize }}</NText>
                </div>
                <div class="info-item">
                    <NText class="color-white" depth="3">{{ $t('log.systemLog.updateTime') }}:</NText>
                    <NText class="color-white">{{ fileInfo.lastUpdate }}</NText>
                </div>
            </div>
        </div>

        <div class="log-content" :style="{ height: sidebarHeight + 'px' }">
            <div class="content-header">
                <div class="search-section">
                    <div class="search-bar">
                        <NInput
                            v-model:value="searchKeyword"
                            :placeholder="$t('log.systemLog.searchKeyword')"
                            clearable
                            @keyup.enter="searchInLog"
                        >
                            <template #suffix>
                                <NButton text @click="searchInLog">
                                    <template #icon>
                                        <icon-uil-search />
                                    </template>
                                </NButton>
                            </template>
                        </NInput>
                    </div>

                    <div v-if="searchResults.length > 0" class="search-navigation">
                        <NText depth="3" style="font-size: 12px">
                            {{ currentSearchIndex + 1 }} / {{ searchResults.length }}
                        </NText>
                        <NButtonGroup size="small">
                            <NButton @click="prevSearchResult">
                                <template #icon>
                                    <icon-uil-angle-up />
                                </template>
                            </NButton>
                            <NButton @click="nextSearchResult">
                                <template #icon>
                                    <icon-uil-angle-down />
                                </template>
                            </NButton>
                        </NButtonGroup>
                    </div>
                </div>

                <div class="actions">
                    <NButton @click="scrollToTop" size="medium" :disabled="!logLines.length">
                        {{ $t('log.systemLog.top') }}
                    </NButton>
                    <NButton @click="scrollToBottom" size="medium" :disabled="!logLines.length">
                        {{ $t('log.systemLog.bottom') }}
                    </NButton>
                    <NButton @click="clearLog" size="medium" :disabled="!logLines.length">
                        {{ $t('log.systemLog.clearLog') }}
                    </NButton>
                    <NButton
                        @click="isReading ? stopReading() : startReading()"
                        :type="isReading ? 'error' : 'success'"
                        :disabled="!selectedFile"
                        size="medium"
                    >
                        {{ isReading ? $t('log.systemLog.stopMonitoring') : $t('log.systemLog.startMonitoring') }}
                    </NButton>
                </div>
            </div>

            <div class="log-viewer" :style="{ height: logViewerHeight + 'px' }">
                <VirtualLogViewer
                    ref="virtualLogRef"
                    :logs="logLines"
                    :search-keyword="searchKeyword"
                    :height="logViewerHeight"
                    :item-height="20"
                    language="naive-log"
                    :auto-scroll="isReading"
                />
            </div>
        </div>
    </div>
</template>

<style scoped>
.system-log-container {
    display: flex;
    gap: 16px;
    padding: 16px;
    overflow: hidden;
}

.log-sidebar {
    width: 300px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    overflow: hidden;
}

.sidebar-header {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex-shrink: 0;
}

.selected-dir {
    padding: 8px;
    background: #ffffff;
    border: 1px solid var(--n-border-color);
    border-radius: 6px;
    word-break: break-all;
}

.selected-dir .n-text {
    color: #333333 !important;
}

.file-list {
    flex: 1;
    overflow-y: auto;
    border: 1px solid var(--n-border-color);
    border-radius: 6px;
    background: var(--n-card-color);
}

.file-list .n-list-item {
    transition: all 0.2s ease;
    cursor: pointer;
    border-radius: 4px;
    margin: 2px 4px;
}

.file-list .n-list-item:hover {
    background: var(--n-color-hover) !important;
}

.file-list .n-list-item.active {
    background: var(--n-primary-color-suppl) !important;
    color: var(--n-primary-color) !important;
    border-left: 3px solid var(--n-primary-color);
    font-weight: 500;
}

.file-list .n-list-item.active .n-text {
    color: var(--n-primary-color) !important;
    font-weight: 500;
}

.file-info {
    padding: 12px;
    background: #ffffff;
    border: 1px solid var(--n-border-color);
    border-radius: 6px;
    flex-shrink: 0;
}

.info-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 4px;
}

.info-item .n-text {
    color: #333333 !important;
}

.log-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 16px;
    overflow: hidden;
}

.content-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    flex-shrink: 0;
}

.search-section {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.search-bar {
    max-width: 400px;
}

.search-navigation {
    display: flex;
    align-items: center;
    gap: 8px;
}

.actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}

.log-viewer {
    flex: 1;
    border: 1px solid var(--n-border-color);
    border-radius: 6px;
    overflow: hidden;
}
</style>
